package com.asialjim.wechat.spring.message;

import com.asialjim.wechat.aes.AesException;
import com.asialjim.wechat.aes.WXBizMsgCrypt;
import com.asialjim.wechat.apiservice.constant.WeChatCacheName;
import com.asialjim.wechat.message.*;
import com.asialjim.wechat.pojo.account.WeChatAccount;
import com.asialjim.wechat.pojo.account.WeChatAccountHolder;
import com.asialjim.wechat.pojo.account.WeChatAccountType;
import com.asialjim.wechat.wechataccount.WeChatAccountService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <h1><em>ASIAL JIM JAVA DOC</em></h1><hr/>
 * <h2>CLASS DESCRIPTION <i>[ NAME: WeChatMessageServiceImpl ]</i></h2><strong>
 * <p> we-chat message service
 * </strong><p><p><em>Copyright &copy; Asial Jim Co., LTD</em><hr/>
 *
 * @author Asial Jim &nbsp;&nbsp; <span>Email:<a href="mailto:asialjim@hotmail.com">asialjim@hotmail.com</a> &nbsp;&nbsp; <a href="asialjim@qq.com">asialjim@qq.com</a></span>
 * @version 1.0.0
 * @since 2021/3/11   &nbsp;&nbsp; JDK 8
 */
@Data
@Slf4j
@AllArgsConstructor
public class WeChatMessageServiceImpl implements WeChatMessageService {
    private RedissonClient redis;
    private WxBizMsgCryptServiceImpl cryptServer;
    private WeChatAccountService accountServer;
    private WeChatMessageHandlerSelector messageHandlerSelector;

    @Override
    public boolean checkService(String signature, String timestamp, String nonce, String echostr) {
        return accountServer.allAccounts().stream().anyMatch(account -> {
            try {
                WXBizMsgCrypt crypt = new WXBizMsgCrypt(account.getToken(), account.getEncodingAesKey(), account.getAppId());
                crypt.verifyUrl(signature, timestamp, nonce, echostr);
                log.info("\r\n新增对公众平台账号:{}的服务支持", account.toString());
                return true;
            } catch (AesException e) {
                log.error("\r\n=========\r\n使用:{}\n解密失败,使用下一个公众平台帐号解密\r\n==========", account.toString());
                return false;
            }
        });
    }

    @Override
    public String handle(BaseWeChatCallMessage callMessage, String signature, String timestamp, String nonce, String echostr) {
        log.debug("\r\n\t处理用户交互信息：{},签名：{}，时间：{}，nonce:{}",callMessage,signature,timestamp,nonce);

        // 防重复
        String key = WeChatCacheName.WECHAT_MESSAGE + "inputMsgId:"+callMessage.getCreateTime();
        RBucket<String> bucket = redis.getBucket(key);
        if (Objects.nonNull(bucket.get())){
            return "success";
        }
        bucket.set("handled",20,TimeUnit.MINUTES);
        String toUserName = callMessage.getToUserName();
        WeChatAccount weChatAccount = accountServer.findBySubjectId(toUserName);
        WeChatAccountHolder.set(weChatAccount);

        // 处理消息
        BaseWeChatCallMessage decryptedCallMessage = cryptServer.decrypt(callMessage, signature, timestamp, nonce);
        log.debug("\r\n\t解密后用户交互信息：{}",decryptedCallMessage.toString());
        WeChatMessage wechatMessage = decryptedCallMessage.genWeChatMessage(WeChatAccountType.OFFICIAL_ACCOUNT);
        WeChatMessageHandler handler = messageHandlerSelector.select(decryptedCallMessage.messageTypeName(WeChatAccountType.OFFICIAL_ACCOUNT));
        String handle = handler.handle(wechatMessage,signature,timestamp,nonce, echostr);

        log.info("\r\n\t返回用户消息：{}，结果：{}",callMessage.toString(),handle);
        return handle;
    }
}